package ar.edu.caece.pl.asem.model.impl.treeelements;

import ar.edu.caece.pl.asem.temp.TemporalGenerator;

public class Asignacion extends AbstractElement {

	public Asignacion() {
		this.label = "ASIGNACION";
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Asignacion))
			return false;
		Asignacion other = (Asignacion) obj;
		if (label == null) {
			if (other.label != null)
				return false;
		} else if (!label.equals(other.label))
			return false;
		return true;
	}

	@Override
	public void generateASMCode() {

		StringBuffer sb = new StringBuffer();
		String localContextName = this.getChildren().get(0).getEnvName();
		String id;

		if (this.getChildren().get(0) instanceof Parametro) {
			id = "[bp+"
					+ ((Parametro) this.getChildren().get(0))
							.getMemoryInStack() + ']';
		} else if((this.getChildren().get(0) instanceof Variable && ((Variable) this.getChildren().get(0)).getMemoryInStack() != 0)) {
			id = "[bp-"
					+ ((Variable) this.getChildren().get(0))
							.getMemoryInStack() + ']';
		}else{
			id = localContextName + "_" + this.getChildren().get(0).getName();
		}

		AbstractElement arrayNode = this.getChildren().get(0);
		if (arrayNode instanceof Arreglo) {
			if (this.getChildren().get(1) instanceof Arreglo) {
				// Se crea una variable temporal para guardar el valor del arreglo y
				// despues hacer el intercambio entre arreglos.
				// Temporal para realizar el intercambio de valores.
				String swap = TemporalGenerator.getInstance().generateTemporal();
				this.getChildren().get(1).parent = this;
				this.getChildren().get(1).generateASMCode();
				sb.append(this.getChildren().get(1).code);
				sb.append(TAB + "mov bx, ax" + ENTER);
				sb.append(TAB + "mov ax, 2" + ENTER);
				sb.append(TAB + "mul bx" + ENTER);
				sb.append(TAB + "mov bx, ax" + ENTER);
				sb.append(TAB + "mov di, offset " + this.getChildren().get(1).getEnvName() + "_" + this.getChildren().get(1).getName() + ENTER);
				sb.append(TAB + "add di, bx" + ENTER);
				sb.append(TAB + "mov ax, [di]" + ENTER);
				// Asigno valor a la variable temporal.
				sb.append(TAB + "mov " + swap + ", ax" + ENTER);
				
				// Asigno al arreglo la variable temporal
				arrayNode.parent = this;
				arrayNode.generateASMCode();
				sb.append(arrayNode.code);
				sb.append(TAB + "mov di, offset " + id + ENTER);
				sb.append(TAB + "mov bx, ax" + ENTER);
				sb.append(TAB + "mov ax, 2" + ENTER);
				sb.append(TAB + "mul bx" + ENTER);
				sb.append(TAB + "add di, ax" + ENTER);
				sb.append(TAB + "mov ax, " + swap + ENTER);
			} else {
				// <EXPRESSION>
				arrayNode.parent = this;
				arrayNode.generateASMCode();
				sb.append(arrayNode.code);
				sb.append(TAB + "mov di, offset " + id + ENTER);
				sb.append(TAB + "mov bx, ax" + ENTER);
				sb.append(TAB + "mov ax, 2" + ENTER);
				sb.append(TAB + "mul bx" + ENTER);
				sb.append(TAB + "add di, ax" + ENTER);
				this.getChildren().get(1).parent = this;
				this.getChildren().get(1).generateASMCode();
				sb.append(this.getChildren().get(1).code);
			}
			sb.append(TAB + "mov bx, ax" + ENTER);
			sb.append(TAB + "mov [di], bx" + ENTER);			
			TemporalGenerator.getInstance().releaseTemporal();
		} else {
			this.getChildren().get(1).parent = this;
			this.getChildren().get(1).generateASMCode();
			sb.append(this.getChildren().get(1).code);
			
			if (this.getChildren().get(1) instanceof Arreglo) {
				sb.append(TAB + "mov bx, ax" + ENTER);
				sb.append(TAB + "mov ax, 2" + ENTER);
				sb.append(TAB + "mul bx" + ENTER);
				sb.append(TAB + "mov bx, ax" + ENTER);
				sb.append(TAB + "mov di, offset " + this.getChildren().get(1).getEnvName() + "_" + this.getChildren().get(1).getName() + ENTER);
				sb.append(TAB + "add di, bx" + ENTER);
				sb.append(TAB + "mov ax, [di]" + ENTER);
			}
			// <EXPRESSION>
			sb.append(TAB + "mov " + id + ", ax" + ENTER);
			TemporalGenerator.getInstance().releaseTemporal();
		}
		this.code = sb.toString();
	}

}
